package com.easynet.dvdstore;

/**
 * Simple implementation of the DvdService
 * 
 * @author Dominic Farr
 */
public final class SimpleDvdService implements DvdService {

	private static final String ELLIPSE = "...";
	private DvdRepository dvdRepository;

	public SimpleDvdService(DvdRepository dvdRepository) {
		this.dvdRepository = dvdRepository;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.easynet.dvdstore.DvdService#retrieveDvd(java.lang.String)
	 */
	public Dvd retrieveDvd(String dvdReference) throws DvdNotFoundException {
		validateDvdReference(dvdReference);
		
		Dvd dvd = lookupDvdBy(dvdReference);
		
		return dvd;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.easynet.dvdstore.DvdService#getDvdSummary(java.lang.String)
	 */
	public String getDvdSummary(String dvdReference)
	throws DvdNotFoundException {
		validateDvdReference(dvdReference);
		
		Dvd dvd = lookupDvdBy(dvdReference);
		
		return summarize(dvd.getReference(), dvd.getTitle(), dvd.getReview());
	}

	/**
	 * Formats last word of summary. Adding ellipse and remove any 'convenient
	 * placed punctuation'
	 * 
	 * @param word
	 *            to be formatted
	 * @return word without punctuation and ellipse
	 */
	private Object formatLast(String word) {
		// TODO extend this to handle other punctuation like period,
		// exclamation, etc
		if (word.indexOf(',') == -1) {
			return word.concat(ELLIPSE);
		} else {
			return word.replace(",", "").toString().concat(ELLIPSE);
		}
	}

	/**
	 * Looks up a dvd
	 * 
	 * @param dvdReference
	 *            of the dvd
	 * @return Dvd for dvdReference
	 * 
	 * @throws DvdNotFoundException
	 *             if dvdReference is not found in repository
	 */
	private Dvd lookupDvdBy(String dvdReference) throws DvdNotFoundException {
		Dvd dvd = this.dvdRepository.retrieveDvd(dvdReference);

		if (dvd == null) {
			throw new DvdNotFoundException("Failed to find '" + dvdReference
					+ "'");
		}
		return dvd;
	}


	/**
	 * This summarize the review of dvd to 10 words
	 * 
	 * @param reference
	 *            dvd reference
	 * @param title
	 *            dvd title
	 * @param review
	 *            to be summarized
	 * @return summarized review
	 * 
	 * @throws IllegalArgumentException
	 *             if review is null
	 */
	private String summarize(String reference, String title, String review) {
		if (review == null) {
			throw new IllegalArgumentException("review must not be null.");
		}

		StringBuilder builder = new StringBuilder();

		builder.append("[").append(reference).append("] ").append(title)
				.append(" - ");

		String[] words = review.split("[ ]");

		if (words.length <= 10) {
			return builder.append(review).toString();
		} else {
			for (int i = 0; i < 9; i++) {
				builder.append(words[i]).append(" ");
			}

			builder.append(formatLast(words[9]));

			return builder.toString();
		}
	}

	/**
	 * Performs validation of the dvdReference parameter for service methods
	 * 
	 * @param dvdReference
	 * @throws IllegalArgumentException
	 *             if the dvdReference is null or does not begin with DVD-
	 */
	private void validateDvdReference(String dvdReference) {
		if (dvdReference == null) {
			throw new IllegalArgumentException("dvdReference must not be null.");
		}

		if (!dvdReference.startsWith(DvdService.DVD_REFERENCE_PREFIX)) {
			throw new IllegalArgumentException(
					"All DVD references must start with 'DVD-'"
							+ ", this dvdReference: '" + dvdReference + "'");
		}
	}

}
